#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>

//pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER;   //静态锁创建
pthread_mutex_t *mx ;  // 动态锁创建
pthread_t ntid_1 = 0;
pthread_t ntid_2 = 1;
int common = 1;

void printpid(void);
void *thr_fn_1(void* );
void *thr_fn_2(void* );

void cleanup(void *arg)
{
    printf("cleanup func : %s\n", (char *)arg);
}

void printpid()
{
    pid_t pid;
    pthread_t tid;
    pid = getpid();          //获得进程id
    tid = pthread_self();    //获得线程id
    printf("pid = %u, tid = %u\n", (unsigned int)pid, (unsigned int)tid);
}

void *thr_fn_1(void* arg)
{
    printf("pthread one start\n");
    pthread_cleanup_push(cleanup, "thread 1 first handler");   //进程清理 与 pthread_cleanup_pop 成对出现
    pthread_cleanup_push(cleanup, "thread 1 second handler");  //进程清理工作先调用的后执行
    printf("thread 1 push complete. \n");
    pthread_mutex_lock(mx);              //给线程加锁
    common += 1;
    printf("common = %d\n", common);
    printpid();
    sleep(3);                            
    common += 1;
    printf("common = %d\n", common);
    pthread_cleanup_pop(1);   //参数不是0时候才执行
    pthread_cleanup_pop(1);
    pthread_mutex_unlock(mx);            //给线程解锁
    printf("pthread one end\n");
    return ((void*)1);
}

void *thr_fn_2(void* arg)
{
    printf("pthread two start\n");
    pthread_cleanup_push(cleanup, "thread 2 first handler");
    pthread_cleanup_push(cleanup, "thread 2 second handler");
    pthread_mutex_lock(mx);
    common -= 1;
    printf("common = %d\n", common);
    printf("thread 2 push complete. \n");
    printpid();
    pthread_cleanup_pop(1);
    pthread_cleanup_pop(1);
    pthread_mutex_unlock(mx);
    printf("pthread two end\n");
    pthread_exit((void *)2);
}

int main(void)
{
    int err;
    void *tret;
    mx = malloc(sizeof(pthread_mutex_t));  //分配动态锁
    pthread_mutex_init(mx, NULL);          //对动态锁进行初始化
    err = pthread_create(&ntid_1, NULL, thr_fn_1, NULL);  //创建线程
    if (err != 0) printf("err 1\n");

    err = pthread_create(&ntid_2, NULL, thr_fn_2, NULL);
    if (err != 0) printf("err 1\n");

    pthread_detach(ntid_1);   //线程分离
    if( pthread_join(ntid_1, &tret) == EINVAL ) printf("has detach !\n");  //如果线程分离就不会有退出状态(tret)
    printf("thread 1 exit code %d\n", (int)tret);

    pthread_join(ntid_2, &tret);
    printf("thread 2 exit code %d\n", (int)tret);

    pthread_mutex_destroy(mx);            //用动态锁在结束时候要释放锁
    printf("main\n");
    printpid();
    exit(0);
}
